package com.higgins.eventtracking.client.finance;

import java.util.Date;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.visualization.client.AbstractDataTable;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.VisualizationUtils;
import com.google.gwt.visualization.client.AbstractDataTable.ColumnType;
import com.google.gwt.visualization.client.visualizations.LineChart;
import com.google.gwt.visualization.client.visualizations.LineChart.Options;
import com.google.gwt.visualization.client.visualizations.corechart.BarChart;
import com.higgins.eventtracking.client.AssetTrackingService;
import com.higgins.eventtracking.client.AssetTrackingServiceAsync;
import com.higgins.eventtracking.client.FinanceTrackingService;
import com.higgins.eventtracking.client.FinanceTrackingServiceAsync;
import com.higgins.eventtracking.client.SecurityAccessDeniedException;
import com.higgins.eventtracking.client.dto.ChartDataDTO;
import com.higgins.eventtracking.client.dto.TransactionDTO;

public class Charts extends VerticalPanel		{
	
	private static final String SERVER_ERROR = "An error occurred while "
		+ "attempting to contact the server. Please check your network "
		+ "connection and try again.";
	private final FinanceTrackingServiceAsync financeTrackingService = GWT
			.create(FinanceTrackingService.class);
	private final AssetTrackingServiceAsync assetTrackingService = GWT
			.create(AssetTrackingService.class);
	
	private LineChart line = null;
	private final ListBox chartPointsListBox = new ListBox();
	private final ListBox periodListBox = new ListBox();
	private final ListBox chartTypeListBox = new ListBox();
	private final ListBox chartOffsetListBox = new ListBox();
	private final FinanceTrackingServiceAsync financeService = GWT
	.create(FinanceTrackingService.class);
	private Runnable onLoadCallback ;
	private String weeklyChartMenuItem = "Weekly";
	private String monthlyChartMenuItem = "Monthly";
	private String breakdown = "Breakdown";
	private String chart = "Chart";
	private String goals = "Goals";
	private String savings = "Savings";
	private boolean firstRun = true;

	
	public Charts()			{
	}
	
	public void update()	{
		if (firstRun)	{
			initialise();
		} else {
			refresh();
		}
	}
	public void initialise()	{
		firstRun = false;
		attachComponents();
		populateChartOffsetList();
		populateChartPointsList();
		populateChartTypeList();
		executeChart();
	}
	public void refresh()	{
		
	}
	private void attachComponents()	{
		add(periodListBox);
		add(chartTypeListBox);
		add(chartOffsetListBox);
		add(chartPointsListBox);
	}
	private void populateChartPointsList()	{
		chartPointsListBox.addItem("1");
		chartPointsListBox.addItem("2");
		chartPointsListBox.addItem("3");
		chartPointsListBox.addItem("4");
		chartPointsListBox.addItem("5");
		chartPointsListBox.addItem("6");
		chartPointsListBox.addItem("7");
		chartPointsListBox.addItem("8");
		chartPointsListBox.addItem("9");
		chartPointsListBox.addItem("10");
		chartPointsListBox.addItem("11");
		chartPointsListBox.addItem("12");
		chartPointsListBox.addItem("13");
		chartPointsListBox.addItem("14");
		chartPointsListBox.addItem("15");
		chartPointsListBox.addItem("16");
		chartPointsListBox.addItem("17");
		chartPointsListBox.addItem("18");
		chartPointsListBox.addItem("19");
		chartPointsListBox.addItem("20");
		chartPointsListBox.addItem("21");
		chartPointsListBox.addItem("22");
		chartPointsListBox.addItem("23");
		chartPointsListBox.addItem("24");
		chartPointsListBox.addItem("25");
		chartPointsListBox.addItem("26");
		chartPointsListBox.setSelectedIndex(0);
		chartPointsListBox.addChangeHandler(new FinanceChartHandler());		
	}
	private void populateChartOffsetList()	{
		chartOffsetListBox.addItem("1");
		chartOffsetListBox.addItem("2");
		chartOffsetListBox.addItem("3");
		chartOffsetListBox.addItem("4");
		chartOffsetListBox.addItem("5");
		chartOffsetListBox.addItem("6");
		chartOffsetListBox.addItem("7");
		chartOffsetListBox.addItem("8");
		chartOffsetListBox.addItem("9");
		chartOffsetListBox.addItem("10");
		chartOffsetListBox.addItem("11");
		chartOffsetListBox.addItem("12");
		chartOffsetListBox.addItem("13");
		chartOffsetListBox.addItem("14");
		chartOffsetListBox.addItem("15");
		chartOffsetListBox.addItem("16");
		chartOffsetListBox.addItem("17");
		chartOffsetListBox.addItem("18");
		chartOffsetListBox.addItem("19");
		chartOffsetListBox.addItem("20");
		chartOffsetListBox.addItem("21");
		chartOffsetListBox.addItem("22");
		chartOffsetListBox.addItem("23");
		chartOffsetListBox.addItem("24");
		chartOffsetListBox.addItem("25");
		chartOffsetListBox.addItem("26");
		chartOffsetListBox.setSelectedIndex(11);
		chartOffsetListBox.addChangeHandler(new FinanceChartHandler());		
	}	
	private void populateChartTypeList()	{
		periodListBox.addItem(weeklyChartMenuItem);
		periodListBox.addItem(monthlyChartMenuItem);
		periodListBox.addChangeHandler(new FinanceChartHandler());		
		chartTypeListBox.addItem(chart);
		chartTypeListBox.addItem(breakdown);
		chartTypeListBox.addItem(goals);
		chartTypeListBox.addItem(savings);
		chartTypeListBox.addChangeHandler(new FinanceChartHandler());		
	}
	private boolean isWeeklyChart()	{
		int selectedItem = periodListBox.getSelectedIndex();
		return periodListBox.getValue(selectedItem).equals(weeklyChartMenuItem);
	}
	private boolean isBreakdownChart()	{
		int selectedItem = chartTypeListBox.getSelectedIndex();
		return chartTypeListBox.getValue(selectedItem).equals(breakdown);
	}
	private Integer numberOfPoints()	{
		int selectedItem = chartPointsListBox.getSelectedIndex();
		return Integer.valueOf(chartPointsListBox.getValue(selectedItem));
	}
	private Integer numberOfOffset()	{
		int selectedItem = chartOffsetListBox.getSelectedIndex();
		return Integer.valueOf(chartOffsetListBox.getValue(selectedItem));
	}	
	private boolean isGoalsChart()	{
		int selectedItem = chartTypeListBox.getSelectedIndex();
		return chartTypeListBox.getValue(selectedItem).equals(goals);
	}	
	private boolean isSavingsChart()	{
		int selectedItem = chartTypeListBox.getSelectedIndex();
		return chartTypeListBox.getValue(selectedItem).equals(savings);
	}	
	
	private void executeChart()	{
		if (isSavingsChart())	{
			financeService.retrieveFinanceSavingsData(chartOffsetListBox.getSelectedIndex(),	new AsyncCallback<ChartDataDTO>() {
				public void onFailure(Throwable caught) {

				}
				public void onSuccess(final ChartDataDTO results) {
					runCharts(results);
				}
			});			
		} else if (isGoalsChart())	{
			financeService.retrieveFinanceGoalsData(chartOffsetListBox.getSelectedIndex(),	new AsyncCallback<ChartDataDTO>() {
						public void onFailure(Throwable caught) {

						}
						public void onSuccess(final ChartDataDTO results) {
							runCharts(results);
						}
					});			
		}	else if (isBreakdownChart())	{
			financeService.retrieveFinanceBreakdownChartData(isWeeklyChart(), true, numberOfOffset(), numberOfPoints(),  
					new AsyncCallback<ChartDataDTO>() {
						public void onFailure(Throwable caught) {
						}
						public void onSuccess(final ChartDataDTO results) {
							runCharts(results);
						}
					});
		} else	{
			financeService.retrieveFinanceChartData(isWeeklyChart(), true, numberOfOffset(), 
					new AsyncCallback<ChartDataDTO>() {
						public void onFailure(Throwable caught) {
						}
						public void onSuccess(final ChartDataDTO results) {
							runCharts(results);
						}
					});
			
		}
	}
	
	private void updateChart()	{
		if (isSavingsChart())	{
			financeService.retrieveFinanceSavingsData(chartOffsetListBox.getSelectedIndex(),	new AsyncCallback<ChartDataDTO>() {
				public void onFailure(Throwable caught) {

				}
				public void onSuccess(final ChartDataDTO results) {
					line.draw(createTable(results), createOptions());
				}
			});			
		} else if (isGoalsChart())	{
			financeService.retrieveFinanceGoalsData(chartOffsetListBox.getSelectedIndex(),	new AsyncCallback<ChartDataDTO>() {
						public void onFailure(Throwable caught) {

						}
						public void onSuccess(final ChartDataDTO results) {
							line.draw(createTable(results), createOptions());
						}
					});			
		}	else if (isBreakdownChart())	{
			financeService.retrieveFinanceBreakdownChartData(isWeeklyChart(), true, numberOfOffset(), numberOfPoints(), 
					new AsyncCallback<ChartDataDTO>() {
						public void onFailure(Throwable caught) {
						}
						public void onSuccess(final ChartDataDTO results) {
							line.draw(createTable(results), createOptions());
						}
					});
		} else 	{
			financeService.retrieveFinanceChartData(isWeeklyChart(), true, numberOfOffset(), 
					new AsyncCallback<ChartDataDTO>() {
						public void onFailure(Throwable caught) {
						}
						public void onSuccess(final ChartDataDTO results) {
							line.draw(createTable(results), createOptions());
						}
					});
			
		}
	}	
		
	 private void runCharts(final ChartDataDTO results)	{
       	onLoadCallback = new Runnable() {
	        public void run() {
	        	line = new LineChart(createTable(results), createOptions());
	        	add(line);
	        }
	      };
		
//		VisualizationUtils.loadVisualizationApi(onLoadCallback, LineChart.PACKAGE);
		VisualizationUtils.loadVisualizationApi(onLoadCallback, BarChart.PACKAGE);
	 }
		
		
	  private Options createOptions() {
	    Options options = Options.create();
	    options.setWidth(600);
	    options.setHeight(400);
	    options.setTitle("Finances");
	    String xTitle = isWeeklyChart()?weeklyChartMenuItem:monthlyChartMenuItem;
	    options.setTitleX(xTitle.substring(0, xTitle.length()-2));
	    options.setTitleY("Amount");
	    return options;
	  }

	  private DataTable createTable(ChartDataDTO results) {
		  	List<Double> items = results.getData();
		  	List<Double> itemsTwo = results.getDataTwo();
		  	List<String> axis = results.getXAxis();
		    DataTable data = DataTable.create();
		    data.addColumn(ColumnType.STRING, "Date");
		    if (itemsTwo!=null)	{
			    data.addColumn(ColumnType.NUMBER, "Goal");
			    data.addColumn(ColumnType.NUMBER, "Savings");
		    } else	{
			    data.addColumn(ColumnType.NUMBER, "Amount");
		    }
		    data.addRows(items.size());
		    int count = 0;
		    for (Double item:items)	{
		    	data.setValue(count, 0, axis.get(count));
		        data.setValue(count, 1, item);
			    if (itemsTwo!=null)	{
			        data.setValue(count, 2, itemsTwo.get(count));
			    }
			    count++;
		    }
	    return data;
	  }
		  
	class FinanceChartHandler implements ChangeHandler {
		public void onChange(ChangeEvent event) {
			updateChart();
		}
	}	
}
